import 'package:simulator/core/arch.dart';
import 'package:simulator/core/blocdev.dart';
import 'package:simulator/core/block.dart';
import 'package:simulator/core/cpu.dart';
import 'package:simulator/core/monitor.dart';
import 'package:simulator/core/ram.dart';
import 'package:simulator/core/run.dart';
import 'package:simulator/core/socket.dart';
import 'package:simulator/utils/module.dart';
import 'package:simulator/utils/options.dart';
import 'package:simulator/utils/os.dart';
import 'package:simulator/utils/utils.dart';

class Simulator {
  static final Simulator _instance = Simulator._internal();
  Simulator._internal();

  static Simulator getInstance() => _instance;

  void init(List<String> args) {
    Options.getInstance().addOpts(simuDriveOpts);
    Options.getInstance().addOpts(simuLegacyDriveOpts, isVm: false);
    Options.getInstance().addOpts(simuCommonDriveOpts, isVm: false);
    Options.getInstance().addOpts(simuDriveOpts, isVm: false);
    Options.getInstance().addOpts(bdrvRuntimeOpts, isVm: false);

    /// [todo]
    moduleCallInit(ModuleInitType.opts);
    Utils.getInstance().init();
    OS.getInstance().setupLimits();
    Arch.getInstance().initArchModules();
    _initSubSystem();
    Options.getInstance().parserAndValidate(args);
    // if (Options.optDict.wasParsed('mem-prealloc')) {
    //   _processSugarOptions(memPrealloc: Options.optDict['mem-prealloc']);
    // }
    Options.getInstance().processEarlyOptions();
    Options.getInstance().processHelpOptions();
    _maybeDaemonize();
  }

  int mainLoopShouldExit() {
    return 0;
  }

  void mainLoopWait(bool nonblocking) {}

  void _maybeDaemonize() {}

  void _initSubSystem() {
    OS.getInstance().setLineBuffering();
    moduleCallInit(ModuleInitType.trace);
    CPU.getInstance().initLoop();
    Utils.getInstance().addShutdownHook(SimuRunState.exitNotifiersHook);
    moduleCallInit(ModuleInitType.qom);
    moduleCallInit(ModuleInitType.migrattion);

    SimuRunState.getInstance().runstateInit();
    RAM.getInstance().precopyInfrastructureInit();
    PostCopyRAM.getInstance().postcopyInfrastructureInit();
    Monitor.getInstance().initGlobals();
    OS.getInstance().setupSignal();
    Block.getInstance().init();
    SimuSocket.getInstance();
  }

  void cleanup() {}
}
